package com.iti.jets.gpts.dao;

import com.iti.jets.gpts.dto.DTO;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;

import java.util.List;

import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Example;

public abstract class AbstractDAO<T extends DTO> implements DAO<T> {
    protected Session session;
    protected Class<T> entityClass;

    public AbstractDAO(SessionFactory sessionFactory) {
        session = sessionFactory.openSession();
        entityClass = ((Class) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0]);
    }

    public AbstractDAO(SessionFactory sessionFactory, Interceptor interceptor) {
        session = sessionFactory.openSession(interceptor);
        entityClass = ((Class) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0]);
    }

    @Override
    public void create(T object) {
        // TODO Implement this method
        session.beginTransaction();
        session.save(object);
        session.getTransaction().commit();
    }

    @Override
    public void delete(T object) {
        // TODO Implement this method
        session.beginTransaction();
        session.delete(object);
        session.getTransaction().commit();
    }

    @Override
    public List<T> loadAll() {
        // TODO Implement this method
        return session.createCriteria(entityClass).list();
    }

    @Override
    public T read(Serializable id) {
        // TODO Implement this method
        return (T) session.get(entityClass, id);
    }

    @Override
    public void update(T object) {
        // TODO Implement this method
        session.beginTransaction();
        session.update(object);
        session.getTransaction().commit();
    }

    @Override
    protected void finalize() throws Throwable {
        // TODO Implement this method
        session.close();
        super.finalize();
    }

    @Override
    public boolean exists(T object) {
        Example exampleT = Example.create(object);
        return session.createCriteria(entityClass)
                .add(exampleT).uniqueResult() != null;
    }
}
